<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="ColorVertexShader" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform float u_PointSize;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        gl_PointSize = u_PointSize;
    }
</script>
<script id="ColorFragmentShader" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    void main(){
        gl_FragColor = u_Color;
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'



    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    // gl.enable(gl.DEPTH_TEST);//开始背景遮挡会频闪
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion

    const scene = new Scene({ gl: gl });

    scene.regProgram('color', {
        program: CreateProgram(gl,
            document.querySelector('#ColorVertexShader').innerText,
            document.querySelector('#ColorFragmentShader').innerText),
        attribs: ['a_Position'],
        uniforms: ['u_PvM4', 'u_ModelM4', 'u_PointSize', 'u_Color']
    })



    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4()

    const eye = new Vector3(-1, 1, 3);
    const lookAt = new Vector3(0, 0, 0);

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4,
        rendEvent: draw,
        eye,
        lookAt,
    });

    const nodeLength = 0.3;
    const nodeArr = [
        -nodeLength, 0, -nodeLength,
        -nodeLength, 0, nodeLength,
        nodeLength, 0, nodeLength,
        nodeLength, 0, -nodeLength,
    ];

    const elementArr = [
        0, 1, 2,
        0, 2, 3,
    ];


    {
        let obj01 = new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(nodeArr) },
                },
                element: {
                    array: new Uint8Array(elementArr)
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['TRIANGLES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_PointSize': { type: 'uniform1f', value: 30 },
                    'u_Color': { type: 'uniform4fv', value: [1, 1, 1, 1] },
                },
            }),
        });
        scene.add(obj01);
        let axis = new Obj3D().createAxis('color');
        scene.add(axis);

        let center = getCenter(obj01);
        scene.add(createNode(center));


        draw();



        // 如果向视线方向移动
        // 先获取方向
        // 方向
        let V = eye.clone().sub(center).normalize();
        scene.add(createLine(center, V, [1, 1, 0, 1]));
        //移动距离
        let J = 1;


        // 画出移动后的位置
        let M = V.multiplyScalar(J);
        scene.add(createNode(M, [0, 0, 1, 1]));
        scene.add(createLine(center, M, [1, 0, 1, 1]));



        // 画出方向基准的位置
        // scene.add(createNode(eye));
        // scene.add(createLine(center, eye, [1, 0, 0, 1]));


        // 画平面出移动后的位置
        const { array } = obj01.geo.data['a_Position'];
        const posiArray = [];
        for (let i = 0; i < array.length; i += 3) {
            let posi = new Vector3(array[i], array[i + 1], array[i + 2]).add(M);
            posiArray.push(posi.x, posi.y, posi.z);
        }

        let obj02 = new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(posiArray) },
                },
                element: {
                    array: new Uint8Array(elementArr)
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['TRIANGLES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_PointSize': { type: 'uniform1f', value: 30 },
                    'u_Color': { type: 'uniform4fv', value: [1, 1, 1, 1] },
                },
            }),
        });
        scene.add(obj02);


        draw();
    }


    function createLine(a, b, color = [1, 0, 0, 1]) {
        return new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array([a.x, a.y, a.z, b.x, b.y, b.z]) },
                },
                element: { array: new Uint8Array([0, 1]) }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['LINES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_PointSize': { type: 'uniform1f', value: 10 },
                    'u_Color': { type: 'uniform4fv', value: color },
                },
            }),
        });
    }

    function createNode(vec3, color = [1, 0, 0, 1]) {
        return new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array([vec3.x, vec3.y, vec3.z]) },
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['POINTS'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_PointSize': { type: 'uniform1f', value: 10 },
                    'u_Color': { type: 'uniform4fv', value: color },
                },
            }),
        });
    }

    //查询中心点,仅限规格四边形
    function getCenter(obj3D) {
        const { array } = obj3D.geo.data['a_Position'];
        const { value } = obj3D.mat.data['u_ModelM4'];

        let modelM4 = new Matrix4(
            value[0], value[1], value[2], value[3],
            value[4], value[5], value[6], value[7],
            value[8], value[9], value[10], value[11],
            value[12], value[13], value[14], value[15],
        );
        //第一个点
        const a = new Vector3(array[0], array[1], array[2]).applyMatrix4(modelM4);
        const index = (array.length / 3 / 4 - 1) * 4 + 2;
        const b = new Vector3(array[index * 3], array[index * 3 + 1], array[index * 3 + 2]).applyMatrix4(modelM4);

        const [x, y, z] = [b.x - a.x, b.y - a.y, b.z - a.z];

        return b.clone().sub(a).multiplyScalar(0.5).add(a);
    }

    function draw() {

        scene.setUniform('u_PvM4', { value: pvM4.elements });
        scene.draw();
    }
</script>

</html>